# Python API reference ## Table of contents - [Python API reference](#python-api-reference) - [Registering applications](#registering-applications) - [Running applications](#running-applications) - [Finding objects](#finding-objects) - [Accessing properties and methods](#accessing-properties-and-methods) - [Synchronization](#synchronization) - [Connections and Bindings](#connections-and-bindings) - [Mouse and keyboard](#mouse-and-keyboard) - [Touch devices](#touch-devices) - [Gestures](#gestures) - [Screenshots](#screenshots) - [Qt types](#qt-types) ## Registering applications Available applications are defined in files named ___applications.json___. They contain a list of applications names mapped to their path and default arguments. Two different files are used: a local one in the current folder and a shared one in the user folder. Applications registered in the shared file will be globally available from any script and any test suite. These files can be edited in any text editor, with the Qat GUI or with the following API functions: ```python def register_application(name: str, path: str, args='', shared=None) -> None ``` Adds the given application to the current ___applications.json___ file. - __name__ Must be a unique name for this application. It will be used when calling _qat.start_application()_ for example. - __path__ The absolute path to the application executable. - __args__ (optional) The default arguments used when launching the application (e.g. when using Qat-Spy). They can be overridden when calling _qat.start_application()_. - __shared__ (optional) _True_ to use the shared (global) file, _False_ to use the local one. If _None_ (default), the local file will be used if it exists otherwise the shared one will be used.
```python def unregister_application(name: str, shared=None) -> None ``` Removes the given application from the current ___applications.json___ file. - __name__ The unique name of the application, must be the same as the one given to _register_application()_. - __shared__ _True_ to use the shared (global) file, _False_ to use the local one. If _None_, the local file will be used if it exists otherwise the shared one will be used. > _Note:_ If the given application does not exist in the current ___applications.json___ file, this function does nothing.
```python def get_application_path(name: str) -> str ``` Returns the path of the given application from the current ___applications.json___ file. - __name__ The unique name of the application, must be the same as the one given to _register_application()_.
```python def get_config_file(shared=None) -> Path ``` Returns the path to the current ___applications.json___ file. - __shared__ _True_ to use the shared (global) file, _False_ to use the local one. If _shared_ is _None_ and if a configuration file exists in the current working directory, it will be returned. Otherwise, the global one from the user directory (e.g. _~/.qat_) will be returned if it exists. Finally, if no file exists, the path to a default file in the current working directory will be returned.
```python def list_applications() -> dict ``` Returns the list of registered applications. The contents of both local and shared configurations is merged. Values from the local configuration take precedence: if an application is registered in both configurations with different paths or arguments, the values from the local configuration will be returned. ## Running applications The following API function starts the given application. ```python def start_application(app_name: str, args = None, detached = False) -> ApplicationContext ``` > _Notes:_ > > The application must be registered in ___applications.json___. > > The function will raise an exception if the application could not start before _testSettings.wait_for_app_start_timeout_. > > The function will raise an exception if the application is started on an unsupported system. When _detached_ is True, the application will start without initializing Qat. This is useful when testing cases where the application returns early (e.g. in case of errors such as invalid arguments). The returned _ApplicationContext_ can still be used to retrieve the corresponding exit code and process ID. The returned _ApplicationContext_ uniquely identifies the started application instance. This allows multiple applications / instances to be launched at the same time. To switch between applications, the current _ApplicationContext_ must be changed: ```python def set_current_application_context(app_context: ApplicationContext) ``` All subsequent API calls will then be redirected to the application identified by _app_context_. > _Note:_ Objects already retrieved with _wait_for_object\[\_exists]()_ or similar functions (see sections below) will still be linked to their original _ApplicationContext_. You need to get a new Object instance if you want to interact with the same object but in another application instance. The current application context can be retrieved with the following function: ```python def current_application_context() -> ApplicationContext ```
The _close_application()_ function terminates the application identified by the given context and returns its exit code. ```python def close_application(app_context: None) -> int ``` - __app_context__ The context of the application to be closed. If _None_, the current context will be used.
You can also attach Qat to an already running application: ```python def attach_to_application(name_or_pid) -> ApplicationContext ``` - __name_or_pid__ can be the name of a registered application, the name of a (running) executable file or a process ID. > _Note:_ On linux, the application must have been launched by Qat (by calling _qat.start_application()_) for this function to work.
By default, all applications started with _qat.start_application()_ will be automatically closed when a script terminates. To disable this behavior and let applications run after a script terminates, applications must be _detached_. Once detached, applications will not be available to the API anymore and will not be closed when the calling script terminates. To access an application again, the _attach_to_application()_ function must be called. ```python def detach(contexts = None): ``` - __contexts__ an _ApplicationContext_ or a list of _ApplicationContext_. If None (default), all current applications will be detached.
To prevent user activity from affecting test results, tested applications can be "locked": they will ignore events such as mouse clicks and moves, keyboard input and focus changes. ```python def lock_application() def unlock_application() ``` By default, Qat locks all applications when running tests in release mode. Applications are unlocked in debug mode to allow you to interact with the application while debugging a test. This behavior can be changed by editing *lockUI* parameter in the _testSettings.json_ file. ## Finding objects ```python def list_top_windows() -> list ``` This functions returns a list of all top windows existing in the application, including the ones that are not currently open/visible.
```python def wait_for_object_exists(definition: dict, timeout = Settings.wait_for_object_timeout) -> QtObject ``` This function searches for the unique object corresponding to the given definition. It returns an Object that can be used to access properties and methods of the remote object (see [section](#accessing-properties-and-functions) below). It raises a LookupError if the object cannot be found before the given timeout (in milliseconds) or if there are multiple objects matching the given definition. The definition can be: - A dictionary of property names and values, - A string containing a unique _objectName_, - An Object previously returned by any _wait_for*()_ function __Example__: ```python definition = { 'objectName': 'someButton', 'type': 'Button', 'text': 'Ok' } button1 = qat.wait_for_object_exists(definition) button2 = qat.wait_for_object_exists('someButton') button3 = qat.wait_for_object_exists(button1) ``` Assuming 'someButton' is a unique _objectName_, all three calls will return the same Button instance. > This applies to all API functions accepting a _definition_ in their arguments.
```python def wait_for_object(definition: dict, timeout = Settings.wait_for_object_timeout) -> QtObject ``` This function is similar to the previous one but also waits for the object to be accessible (i.e. visible and enabled).
```python def wait_for_object_missing(definition: dict, timeout = Settings.wait_for_object_timeout) ``` This function waits for the given object to be deleted from the application i.e it waits until wait_for_object_exists() fails. It raises a TimeoutError if the given object still exists after the given timeout (in milliseoncds) has been reached.
```python def find_all_objects(definition: dict, timeout = Settings.wait_for_object_timeout) -> list ``` This function returns a list of Objects that match the given definition.
To retrieve all children of a given object, you can use the ___children___ property: ```python parent = qat.wait_for_object_exists(parent_definition) for child in parent.children: print(child.objectName) ``` ## Accessing properties and methods Any property or method accessible through Qt's _MetaObject_ system is available to the Qat API. This means all _Q_INVOKABLE_ methods and all _Q_PROPERTY_-defined members, including QML objects and custom C++ objects. > Any property/method accessible by QML is also accessible from the Qat API. Properties are automatically mapped to Python attributes of the objects returned by functions such as _wait_for_object_ and _wait_for_object_exists_ (see section above). If a property is writeable, its value can be changed with a normal assignment in Python: ```python button_def = { 'objectName': "someUniqueName", 'type': 'Button' } button = qat.wait_for_object(button_def) # Verify that the right object has been found assert button.objectName == "someUniqueName" # Change the button's width to be twice its height button.width = 2 * button.height ``` It is also possible to retrieve all properties along with their current values by calling _list_properties()_ on an object: ```python for name, value in object.list_properties(): print(f'Property "{name}" is {value}') ``` In a similar way, _methods_ can be called on Objects: ```python panel_def = { 'objectName': "somePanelName", 'type': 'PanelLayout' } panel = qat.wait_for_object(panel_def) # Access the 'proxy' property, which can be a C++ context proxy proxy = panel.proxy # Call the saveData() method on the proxy. # Argument(s) must match the function's prototype. proxy.saveData(True) ``` The _list_methods()_ function returns all available methods: ```python for method_type, signature, return_type in object.list_methods(): print(f'[{method_type}] {return_type} {signature}') ``` > _method_type_ can be one of "signal", "slot", or empty for other methods. ## Synchronization Although Qat executes functions synchronously, some changes may occur asynchronously in the tested application. For example, clicking on a widget may update some binding that will be evaluated later by the Qt Event loop. To avoid timing issues when running tests, the following functions can be used to provide synchronization points: ```python def wait_for_property_value( definition: dict, property_name: str, new_value, comparator = None, check = False, timeout = Settings.wait_for_object_timeout) -> bool ``` This function waits for the given object's property to reach the given value. It returns True if the value was reached, False otherwise. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __property_name__: the name of the property to wait for - __new_value__: the value to reach - __comparator__: Callable used to compare property values. == is used by default. - __check__: If True, raises an exception in case of failure. False by default. - __timeout__: If the new_value is not reached after this timeout, return False.
```python def wait_for_property_change( definition: dict, property_name: str, old_value, comparator = None, check = False, timeout = Settings.wait_for_object_timeout) -> bool ``` This function waits for the given object's property to change its value. It returns True if the value has changed, False otherwise. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __property_name__: the name of the property to wait for - __old_value__: the original value - __comparator__: Callable used to compare property values. == is used by default. - __check__: If True, raises an exception in case of failure. False by default. - __timeout__: If the property value has not changed after this timeout, returns False. You can also wait for any given condition using Python's lambdas: ```python def wait_for(condition, timeout = Settings.wait_for_object_timeout) -> bool ``` Example: ```python object_def = {'objectName': 'someText'} object = qat.wait_for_object_exists(object_def) reached = qat.wait_for( lambda: object.text == "0", timeout = 5000 ) if not reached: raise Exception("Condition was not reached in 5 seconds") ``` ## Connections and Bindings Qat uses the Qt's Signal and Slot mechanism to enable tests to react to any change in the tested applications. There are two ways of using this feature: _Connections_ call a custom callback function when a property changes in the tested application, whereas _Bindings_ automatically synchronize a local Python attribute with an object's property in the tested application. ```python def connect(object, property, callback) -> str ``` Connects a signal from the application to the given callback. If 'property' is a signal name, the given callback will be called without argument. If 'property' is a Qt property name, the given callback will be called with one argument containing the new value of the property. Returns a unique identifier for the newly created connection. - __object__: an object definition or an Object returned by _wait_for_object*()_ - __property__: the name of the property or signal to connect to. - __callback__: a Python Callable (e.g. function or lambda)
```python def disconnect(conn_id) ``` Disconnects a signal or property from its callback. - __conn_id__: a connection identifier, as returned by _connect()_
```python def bind(remote_object, remote_property, local_object, local_property) -> qat.Binding ``` Automatically establishes a connection between the given remote object's property and the given local receiver. The returned Binding object can be used to manage the connection. _Note_: this is equivalent to create a Binding object with the same arguments. - __remote_object__: an object definition or an Object returned by _wait_for_object*()_ - __remote_property__: the name of the property or signal to connect to. - __local_object__: any Python object - __local_attribute__: the name of the Python attribute to be connected. Must be an attribute of _local_object_ and be of a compatible type. Example: ```python label = { 'objectName': 'someLabel' } class Receiver(): def __init__(self): self.value = '' def __setattr__(self, name: str, value): print(f'Value changed: {name} => {value}') # Create a binding between the text of the label and the receiver's value receiver = Receiver() binding = qat.bind(label, 'text', receiver, 'value') # Change the text of the label in the application qat.wait_for_object(label).text = 'Some new text' # Verify that the receiver has updated its value assert receiver.value == 'Some new text' ``` The _bind_ function returns a Binding object which provides the following functions: ```python def connect() ``` Connects (or re-connects) this binding to the remote object.
```python def disconnect() ``` Disconnects this binding. Receiver will not be updated anymore. ## Mouse and keyboard To emulate user activity, Qat generates Qt Events in C++ (as opposed to sending OS events and using the mouse cursor). This means that: - Events can be sent when the application is in the background - Mouse cursor is left free to the user - Events may be sent to the target object even if it is not really accessible by the user (e.g. another dialog is above the object, or the object is outside the window boundaries). - Events can be "auto-verified": if not object accepted an event, an exception can be raised to let the test know that something went wrong. The following mouse events are supported: ```python def mouse_press(definition, x, y, modifier, button, check) ``` Press the _button_ of the mouse on the _definition_ object at local coordinates _x, y_ while holding the _modifier_ key. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __x, y__: the coordinates of the event, relative to the object. If not given, event will occur at the center of the object - __modifier__: Optional keyboard modifier. Must be one of the constants in _qat.Modifier_. Default is _NONE_ - __button__: Optional mouse button. Must be one of the constants in _qat.Button_. Default is _LEFT_ - __check__: Optional check. When _True_ this function will raise an exception if no widget accepted the event. Default is _False_.
```python def mouse_release(definition, x, y, modifier, button, check) ``` Release the _button_ of the mouse on the _definition_ object at local coordinates _x, y_ while holding the _modifier_ key. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __x, y__: the coordinates of the event, relative to the object. If not given, event will occur at the center of the object - __modifier__: Optional keyboard modifier. Must be one of the constants in _qat.Modifier_. Default is _NONE_ - __button__: Optional mouse button. Must be one of the constants in _qat.Button_. Default is _LEFT_ - __check__: Optional check. When _True_ this function will raise an exception if no widget accepted the event. Default is _False_.
```python def mouse_click(definition, x, y, modifier, button, check) ``` Click with the _button_ of the mouse on the _definition_ object at local coordinates _x, y_ while holding the _modifier_ key. Equivalent to a _mousePress()_ immediately followed by a _mouseRelease()_. > Note: Sending two mouse_click events quickly will __not__ generate a double-click event. Use __double_click()__ function instead - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __x, y__: the coordinates of the event, relative to the object. If not given, event will occur at the center of the object - __modifier__: Optional keyboard modifier. Must be one of the constants in _qat.Modifier_. Default is _NONE_ - __button__: Optional mouse button. Must be one of the constants in _qat.Button_. Default is _LEFT_ - __check__: Optional check. When _True_ this function will raise an exception if no widget accepted the event. Default is _False_.
```python def double_click(definition, x, y, modifier, button, check) ``` Double-click with the _button_ of the mouse on the _definition_ object at local coordinates _x, y_ while holding the _modifier_ key. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __x, y__: the coordinates of the event, relative to the object. If not given, event will occur at the center of the object - __modifier__: Optional keyboard modifier. Must be one of the constants in _qat.Modifier_. Default is _NONE_ - __button__: Optional mouse button. Must be one of the constants in _qat.Button_. Default is _LEFT_ - __check__: Optional check. When _True_ this function will raise an exception if no widget accepted the event. Default is _False_.
```python def mouse_move(definition, x, y, modifier, button) ``` Move the mouse to the local coordinates _x, y_ of the _definition_ object while holding the _button_ of the mouse and the _modifier_ key. > Note: if mousePress was called before, this will act as drag operation. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __x, y__: the coordinates of the event, relative to the object. If not given, event will occur at the center of the object - __modifier__: Optional keyboard modifier. Must be one of the constants in _qat.Modifier_. Default is _NONE_ - __button__: Optional mouse button. Must be one of the constants in _qat.Button_. Default is _LEFT_
```python def mouse_drag(definition, x, y, dx, dy, modifier, button, check) ``` Drag the mouse by _dx, dy_ pixels from the local coordinates _x, y_ of the _definition_ object while holding the _button_ of the mouse and the _modifier_ key. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __x, y__: the coordinates of the event, relative to the object. If not given, event will occur at the center of the object - __dx, dy__: the number of pixels to move the mouse by, in each direction. - __modifier__: Optional keyboard modifier. Must be one of the constants in _qat.Modifier_. Default is _NONE_ - __button__: Optional mouse button. Must be one of the constants in _qat.Button_. Default is _LEFT_ - __check__: Optional check. When _True_ this function will raise an exception if no widget accepted the event. Default is _False_.
```python def mouse_wheel(definition, x, y, xDegrees, yDegrees, modifier, check) ``` Scroll the mouse wheel by _xDegrees, yDegrees_ at the local coordinates _x, y_ of the _definition_ object while holding the _modifier_ key. > Note: a physical wheel increment generally corresponds to 15 degrees - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __x, y__: the coordinates of the event, relative to the object. If not given, event will occur at the center of the object - __modifier__: Optional keyboard modifier. Must be one of the constants in _qat.Modifier_. Default is _NONE_ - __button__: Optional mouse button. Must be one of the constants in _qat.Button_. Default is _LEFT_ - __check__: Optional check. When _True_ this function will raise an exception if no widget accepted the event. Default is _False_.
Keyboard events are supported by the following functions: ```python def type_in(definition, text: str) ``` Type _text_ in _definition_ object, character by character. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __text__: Any string. Can also use the following special keys: \, \, \, \, \, \, \, \, \
```python def shortcut(definition, key_combination) ``` Triggers the given shortcut on the given object. Shortcut string must follow the Qt syntax, e.g: 'Ctrl+Z, Alt+O, Alt+Shift+R, ...' - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __key_combination__: The key combination to trigger.
```python def press_key(definition, key: str) ``` Press _key_ in _definition_ object. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __key__: Any character. Can also use the following special keys: \, \, \, \, \, \, \, \, \
```python def release_key(definition, key: str) ``` Release _key_ in _definition_ object. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __key__: Any character. Can also use the following special keys: \, \, \, \, \, \, \, \, \ ## Touch devices Qat can simulate events related to touch devices, such as touch screens and touch pads. The following functions support both single and multiple touch points: ```python def touch_tap(definition, x, y, modifier) ``` Tap one or more fingers on the _definition_ object at local coordinates _x, y_ while holding the _modifier_ key. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __x, y__: the coordinates of each finger, relative to the object. If not given, event will occur at the center of the object. Each argument can be a single value (for single touch point) or an array (for multiple touch points). When using arrays, __x__ and __y__ must be of the same size. - __modifier__: Optional keyboard modifier. Must be one of the constants in _qat.Modifier_. Default is _NONE_ > Note: Sending two touch_tap events quickly will __not__ generate a double-tap event. Use __double_click()__ function instead A _touch_tap_ call is equivalent to a _touch_press_ immediately followed by a _touch_release_.
```python def touch_press(definition, x, y, modifier) ``` Press one or more fingers on the _definition_ object at local coordinates _x, y_ while holding the _modifier_ key. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __x, y__: the coordinates of each finger, relative to the object. If not given, event will occur at the center of the object. Each argument can be a single value (for single touch point) or an array (for multiple touch points). When using arrays, __x__ and __y__ must be of the same size. - __modifier__: Optional keyboard modifier. Must be one of the constants in _qat.Modifier_. Default is _NONE_.
```python def touch_release(definition, x, y, modifier) ``` Release one or more fingers on the _definition_ object at local coordinates _x, y_ while holding the _modifier_ key. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __x, y__: the coordinates of each finger, relative to the object. If not given, event will occur at the center of the object. Each argument can be a single value (for single touch point) or an array (for multiple touch points). When using arrays, __x__ and __y__ must be of the same size. - __modifier__: Optional keyboard modifier. Must be one of the constants in _qat.Modifier_. Default is _NONE_.
```python def touch_move(definition, x, y, modifier) ``` Move one or more fingers on the _definition_ object at local coordinates _x, y_ while holding the _modifier_ key. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __x, y__: the coordinates of each finger, relative to the object. If not given, event will occur at the center of the object. Each argument can be a single value (for single touch point) or an array (for multiple touch points). When using arrays, __x__ and __y__ must be of the same size. - __modifier__: Optional keyboard modifier. Must be one of the constants in _qat.Modifier_. Default is _NONE_. > This function has no effect if _touch_press_ was not called on the same object.
```python def touch_drag(definition, x, y, dx, dy, modifier) ``` Press and drag one or more fingers on the _definition_ object starting at local coordinates _x, y_ while holding the _modifier_ key. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __x, y__: start coordinates of each finger, relative to the object. If not given, event will occur at the center of the object. Each argument can be a single value (for single touch point) or an array (for multiple touh points). When using arrays, __x__ and __y__ must be of the same size. - __dx, dy__: the number of pixels to move each finger, relative to the object. Each argument can be a single value (to apply the same movement to all touch points) or an array (to have different movements for each touch point). When using arrays, __dx__ and __dy__ must be of the same size. - __modifier__: Optional keyboard modifier. Must be one of the constants in _qat.Modifier_. Default is _NONE_. ## Gestures Qat also provides some helper functions to simulate complete gestures: ```python def pinch( definition: dict, rotation = 0., translation = None, scale = 1.0): ``` Generates a sequence of touch events representing a pinch gesture. Such gestures are compatible with both the default [_QGestureRecognizer_](https://doc.qt.io/qt-6/qgesturerecognizer.html) (for QWidget-based applications) and QML's [_PinchArea_](https://doc.qt.io/qt-6/qml-qtquick-pincharea.html) and [_MultiTouchArea_](https://doc.qt.io/qt-6/qml-qtquick-multipointtoucharea.html). - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __rotation (optional)__: Total angle of rotation to apply. Value is in degrees and in clockwise direction. - __translation (optional)__: Global translation of the pinch. This corresponds to the translation of the central point between the two fingers. - __scale (optional)__: Variation of the distance between the two fingers, typically representing a zoom factor. For example, if __scale__ is set to 2.0, the distance between the fingers will double between the beginning and the end of the gesture. >All three optional parameters can be combined to define a complete pinch gesture. >The distance between the two fingers during the gesture will be automatically determined based on the target widget's size.
```python def flick(definition: dict, dx, dy) ``` Moves the given Flickable by the given horizontal and vertical distances in pixels. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __dx__: the horizontal distance in pixels - __dy__: the vertical distance in pixels
```python def native_pinch( definition: dict, angle: int = None, scale: float = None, check: bool = False): ``` Generates a [native pinch event](https://doc.qt.io/qt-6/qnativegestureevent.html). Native gesture events are high-level events generated by the operating system, usually from a sequence of trackpad events. - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __angle (optional)__: Total angle of rotation to apply. Value is in degrees and in clockwise direction. - __scale (optional)__: Variation of the distance between the two fingers, typically representing a zoom factor. For example, if __scale__ is set to 2.0, the distance between the fingers will double between the beginning and the end of the gesture. - __check (optional)__: If True, raises an exception in case of failure (i.e when the event is not handled by any widget). False by default. > This function works with QML/QtQuick widgets only. ## Screenshots By default, Qat will take a screenshot of the application when a failure is detected and will add it to the report. This feature can be disabled by setting _logScreenshotOnFail_ to _False_ in the _testSettings.json_ file. At any time, you can take a screenshot of each top-level window and save it to an image file (format will be deduced from extension): ```python def take_screenshot(path = None) ``` If _path_ is not set, the screenshot will be saved into the __screenshots__ folder of the current directory. The file name will be _qat-screenshotN.png_ where N is the index of the window.
You can also grab a screenshot of any widget and manipulate it within your test as a normal Object: ```python def grab_screenshot(definition, delay = 0, timeout = Settings.wait_for_object_timeout) ``` - __definition__: an object definition or an Object returned by _wait_for_object*()_ - __delay__: wait _delay_ milliseconds before taking the screenshot. Default is 0: no delay - __timeout__: Number of milliseconds to wait for the screenshot to be available once taken. If timeout is reached, an exception is raised. > _Warning:_ Since screenshots reside in tested application's memory, and to avoid running out of RAM, the maximum number of screenshots is set to 10. Once this limit is reached, taking a new screenshot will delete the oldest one in memory. When successful, the _grabScreenshot_ function returns an Image object which provides the following functions: ```python def getPixel(x: int, y: int) -> int def getPixelRGBA(x: int, y: int) -> Color def save(file_name: str) ``` _getPixel_ returns the 32-bit value of the pixel at _x, y_. This value is the hexadecimal value of each component __alpha, red, green, blue__ in this order. Example: ```python image = qat.grabScreenshot(someObject) assert image.getPixel(5, 5) == 0xff008000 # opaque green ```
_getPixelRGBA_ returns the color of the pixel at _x, y_ as a Color object. This object has a member for each component __red, green, blue, alpha__. Components can be accessed by index, in this order. Example: ```python pixel = image.getPixelRGBA(10, 10) assert pixel.red == 0 assert pixel.green == 127 assert pixel.blue == 255 assert pixel.alpha == 255 assert pixel[0] == 0 assert pixel[1] == 127 assert pixel[2] == 255 assert pixel[3] == 255 ```
_save_ saves the image to the given file. Format will be deduced from the extension. Raises an exception if image cannot be saved. ```python file_path = Path(os.getcwd()) / 'test_image.png' image.save(str(file_path)) ```
The following members are also available: - __width__: The width of the image, in pixels - __height__: The height of the image, in pixels ## Qt types Common Qt types such as *QPoint*, *QRect*, *QColor* and *QFont* can be interacted with from python scripts by using wrappers from the *qat.qt_types* module. Objects created from these wrappers can be used as arguments in method calls and can be assigned to properties of compatible Qt type. Here is the list of supported types: ```python QColor( name: str = None, *, red: int = None, green: int = None, blue: int = None, alpha: int = None, ) ``` Create a color with the given parameters. The name can be any supported Qt name or ARGB hexadecimal value. If 'alpha' is not set, it will be set to 255 (opaque). >Note: If a name is given, other arguments will be ignored.
```python QBrush ( color: QColor = None, *, style: QBrush.BrushStyle = None ) ``` Create a brush based on the given color and style. If an argument is missing, a default value will be used (black, SolidPattern). >Note: gradients are not supported.
```python QFont ( family: str = None, *, bold: bool = None, italic: bool = None, strikeOut: bool = None, underline: bool = None, fixedPitch: bool = None, pixelSize: int = None, pointSize: int = None, weight: QFont.Weight = None ) ``` Create a font with the given parameters. If an argument is missing, the default value will be used. > Note: 'pixelSize' and 'pointSize' cannot be both set. > Note: 'weight' takes precedence over 'bold'.
```python QPoint ( x: int = 0, y: int = 0 ) ``` Create a point with the given coordinates.
```python QPointF ( x: float = 0.0, y: float = 0.0 ) ``` Create a point with the given coordinates, using floating-point precision.
```python QLine ( p1: QPoint = QPoint(), p2: QPoint = QPoint() ) ``` Create a line between the two given points.
```python QLineF ( p1: QPointF = QPointF(), p2: QPointF = QPointF() ) ``` Create a line between the two given points, using floating-point precision.
```python QSize ( width: int = 0, height: int = 0 ) ``` Create a size with the given width and height.
```python QSizeF ( width: float = 0.0, height: float = 0.0 ) ``` Create a size with the given width and height, using floating-point precision.
```python QRect ( origin: QPoint = QPoint(0, 0), size: QSize = QSize(0,0) ) ``` Create a rectangle with the given origin (top-left corner) and size.
```python QRectF ( origin: QPointF = QPointF(0, 0), size: QSizeF = QSizeF(0, 0) ) ``` Create a rectangle with the given origin (top-left corner) and size, using floating-point precision.
```python QVector2D ( x: float = 0.0, y: float = 0.0 ) ``` Create a 2D vector with the given coordinates.
```python QVector3D ( x: float = 0.0, y: float = 0.0, z: float = 0.0 ) ``` Create a 3D vector with the given coordinates.
```python QVector4D ( x: float = 0.0, y: float = 0.0, z: float = 0.0, w: float = 0.0 ) ``` Create a 4D vector with the given coordinates.
```python QQuaternion ( vector: QVector3D = QVector3D(), scalar: float = 1.0 ) ``` Create a quaternion with the given vector and scalar.
```python QByteArray ( byte_array = array('b') ) ``` Create a Qt byte array from the given array.